package com.mine.modules.sys.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mine.common.config.exception.MineBootException;
import com.mine.common.constant.CacheConstant;
import com.mine.common.constant.CommonConstant;
import com.mine.common.constant.FillRuleConstant;
import com.mine.common.constant.SymbolConstant;
import com.mine.common.domain.vo.Result;
import com.mine.common.utils.FillRuleUtil;
import com.mine.common.utils.JwtUtil;
import com.mine.common.utils.oConvertUtils;
import com.mine.modules.sys.domain.vo.DepartIdModel;
import com.mine.modules.sys.domain.vo.SysDepartTreeModel;
import com.mine.modules.sys.entity.SysDepart;
import com.mine.modules.sys.mapper.SysDepartMapper;
import com.mine.modules.sys.service.ISysDepartService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mine.modules.sys.utils.FindsDepartsChildrenUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.function.Consumer;

/**
 * <p>
 * 组织机构表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-10-09
 */
@Service
@RequiredArgsConstructor
public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart> implements ISysDepartService {

    private final SysDepartMapper departMapper;

    @Override
    public Result<List<SysDepartTreeModel>> queryTreeList(String keywords) {
        Result<List<SysDepartTreeModel>> result = new Result<>();
        try {
            if (oConvertUtils.isNotEmpty(keywords)) {
                List<SysDepartTreeModel> departList = this.queryTreeModelList(keywords);
                result.setResult(departList);
            } else {
                List<SysDepartTreeModel> list = this.queryTreeModelList();
                result.setResult(list);
            }
            result.setSuccess(true);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return result;
    }

    @Override
    public Result<List<SysDepartTreeModel>> queryDepartTreeSync(String parentId, String ids, String primaryKey) {
        Result<List<SysDepartTreeModel>> result = new Result<>();
        try {
            List<SysDepartTreeModel> list = this.queryTreeListByPid(parentId, ids, primaryKey);
            result.setResult(list);
            result.setSuccess(true);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return result;
    }

    @Override
    public Result<?> queryParentIds(String departId, String orgCode) {
        try {
            JSONObject data;
            if (oConvertUtils.isNotEmpty(departId)) {
                data = this.queryAllParentIdByDepartId(departId);
            } else if (oConvertUtils.isNotEmpty(orgCode)) {
                data = this.queryAllParentIdByOrgCode(orgCode);
            } else {
                return Result.error("departId 和 orgCode 不能都为空！");
            }
            return Result.OK(data);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error(e.getMessage());
        }
    }

    @Override
    @CacheEvict(value = {CacheConstant.SYS_DEPARTS_CACHE, CacheConstant.SYS_DEPART_IDS_CACHE}, allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Result<SysDepart> add(SysDepart sysDepart, HttpServletRequest request) {
        Result<SysDepart> result = new Result<SysDepart>();
        String username = JwtUtil.getUserNameByToken(request);
        try {
            sysDepart.setCreateBy(username);
            this.saveDepartData(sysDepart, username);
            //清除部门树内存
            // FindsDepartsChildrenUtil.clearSysDepartTreeList();
            // FindsDepartsChildrenUtil.clearDepartIdModel();
            result.setMessage("添加成功！");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MineBootException("操作失败！");
        }
        return result;
    }

    @Override
    @CacheEvict(value = {CacheConstant.SYS_DEPARTS_CACHE, CacheConstant.SYS_DEPART_IDS_CACHE}, allEntries = true)
    public Result<SysDepart> edit(SysDepart sysDepart, HttpServletRequest request) {
        String username = JwtUtil.getUserNameByToken(request);
        sysDepart.setUpdateBy(username);
        Result<SysDepart> result = new Result<SysDepart>();
        SysDepart sysDepartEntity = this.getById(sysDepart.getId());
        if (sysDepartEntity == null) {
            result.error500("未找到对应实体");
        } else {
            boolean ok = this.updateDepartDataById(sysDepart, username);
            // TODO 返回false说明什么？
            if (ok) {
                //清除部门树内存
                //FindsDepartsChildrenUtil.clearSysDepartTreeList();
                //FindsDepartsChildrenUtil.clearDepartIdModel();
                result.setMessage("修改成功!");
            }
        }
        return result;
    }

    @Override
    @CacheEvict(value = {CacheConstant.SYS_DEPARTS_CACHE, CacheConstant.SYS_DEPART_IDS_CACHE}, allEntries = true)
    public Result<?> delete(String id) {
        SysDepart sysDepart = this.getById(id);
        if (sysDepart == null) {
            return Result.error("未找到对应实体");
        } else {
            this.deleteDepart(id);
            return Result.OK("删除成功!");
        }
    }

    @Override
    public Result<?> deleteBatch(String ids) {
        if (ids == null || "".equals(ids.trim())) {
            return Result.error("参数不识别！");
        } else {
            this.deleteBatchWithChildren(Arrays.asList(ids.split(",")));
            return Result.ok("删除成功!");
        }
    }

    @Override
    public Result<List<DepartIdModel>> queryIdTree() {
        Result<List<DepartIdModel>> result = new Result<>();
        try {
            List<DepartIdModel> list = this.queryDepartIdTreeList();
            result.setResult(list);
            result.setSuccess(true);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return result;
    }

    @Override
    public SysDepart getDepartById(String id) {
        return departMapper.getDepartById(id);
    }


    @Override
    public IPage<SysDepart> getMaxCodeDepart(Page<SysDepart> page, String parentId) {
        if (StringUtils.isNotBlank(parentId)) {
            return page.setRecords(lambdaQuery().eq(SysDepart::getParentId, parentId).orderByDesc(SysDepart::getOrgCode).list());
        } else {
            return page.setRecords(lambdaQuery().isNull(SysDepart::getParentId)
                    .or()
                    .eq(SysDepart::getParentId, "")
                    .list());
        }
    }

    private List<DepartIdModel> queryDepartIdTreeList() {
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
        query.orderByAsc(SysDepart::getDepartOrder);
        List<SysDepart> list = this.list(query);
        // 调用wrapTreeDataToTreeList方法生成树状数据
        List<DepartIdModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToDepartIdTreeList(list);
        return listResult;
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteBatchWithChildren(List<String> ids) {
        List<String> idList = new ArrayList<String>();
        for (String id : ids) {
            idList.add(id);
            this.checkChildrenExists(id, idList);
            //删除部门设置父级的叶子结点
            this.setIzLeaf(id);
        }
        this.removeByIds(idList);
        //根据部门id获取部门角色id
        //根据部门id删除用户与部门关系
        //根据部门id删除部门授权
        //根据部门id删除部门角色
        //根据角色id删除部门角色授权
        //根据角色id删除部门角色用户信息
    }

    /**
     * delete 方法调用
     *
     * @param id
     * @param idList
     */
    private void checkChildrenExists(String id, List<String> idList) {
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        query.eq(SysDepart::getParentId, id);
        List<SysDepart> departList = this.list(query);
        if (departList != null && departList.size() > 0) {
            for (SysDepart depart : departList) {
                idList.add(depart.getId());
                this.checkChildrenExists(depart.getId(), idList);
            }
        }
    }

    public void deleteDepart(String id) {
        //删除部门设置父级的叶子结点
        this.setIzLeaf(id);
        this.removeById(id);
    }

    /**
     * 设置父级节点是否存在叶子结点
     *
     * @param id
     */
    private void setIzLeaf(String id) {
        SysDepart depart = this.getDepartById(id);
        String parentId = depart.getParentId();
        if (oConvertUtils.isNotEmpty(parentId)) {
            long count = this.count(new QueryWrapper<SysDepart>().lambda().eq(SysDepart::getParentId, parentId));
            if (count == 1) {
                //若父节点无其他子节点，则该父节点是叶子节点
                departMapper.setMainLeaf(parentId, CommonConstant.IS_LEAF);
            }
        }
    }

    /**
     * updateDepartDataById 对应 edit 根据部门主键来更新对应的部门数据
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateDepartDataById(SysDepart sysDepart, String username) {
        if (sysDepart != null && username != null) {
            sysDepart.setUpdateTime(new Date());
            sysDepart.setUpdateBy(username);
            this.updateById(sysDepart);
            //update-begin---author:wangshuai ---date:20220307  for：[JTC-119]在部门管理菜单下设置部门负责人 创建用户的时候不需要处理
            //修改部门管理的时候，修改负责部门
            //this.updateChargeDepart(sysDepart);
            //update-begin---author:wangshuai ---date:20220307  for：[JTC-119]在部门管理菜单下设置部门负责人 创建用户的时候不需要处理
            return true;
        } else {
            return false;
        }

    }

    private List<SysDepartTreeModel> queryTreeModelList() {
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
        query.orderByAsc(SysDepart::getDepartOrder);
        List<SysDepart> list = this.list(query);
        List<SysDepartTreeModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToTreeList(list);
        return listResult;
    }

    private List<SysDepartTreeModel> queryTreeModelList(String keywords) {
        List<SysDepartTreeModel> listResult = new ArrayList<>();
        LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
        query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
        if (oConvertUtils.isNotEmpty(keywords)) {
            query.and(e -> e.like(SysDepart::getOrgCode, keywords).or().like(SysDepart::getDepartName, keywords));
        }
        query.orderByAsc(SysDepart::getDepartOrder);
        List<SysDepart> list = this.list(query);
        for (SysDepart depart : list) {
            listResult.add(new SysDepartTreeModel(depart));
        }
        return listResult;
    }

    /**
     * 根据parentId查询部门树
     *
     * @param parentId
     * @param ids        前端回显传递
     * @param primaryKey 主键字段（id或者orgCode）
     */
    private List<SysDepartTreeModel> queryTreeListByPid(String parentId, String ids, String primaryKey) {
        Consumer<LambdaQueryWrapper<SysDepart>> square = i -> {
            if (oConvertUtils.isNotEmpty(ids)) {
                if (CommonConstant.DEPART_KEY_ORG_CODE.equals(primaryKey)) {
                    i.in(SysDepart::getOrgCode, ids.split(SymbolConstant.COMMA));
                } else {
                    i.in(SysDepart::getId, ids.split(SymbolConstant.COMMA));
                }
            } else {
                if (oConvertUtils.isEmpty(parentId)) {
                    i.and(q -> q.isNull(true, SysDepart::getParentId).or().eq(true, SysDepart::getParentId, ""));
                } else {
                    i.eq(true, SysDepart::getParentId, parentId);
                }
            }
        };
        LambdaQueryWrapper<SysDepart> lqw = new LambdaQueryWrapper<>();
        //------------------------------------------------------------------------------------------------
        lqw.eq(true, SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
        lqw.func(square);
        //update-begin---author:wangshuai ---date:20220527  for：[VUEN-1143]排序不对，vue3和2应该都有问题，应该按照升序排------------
        lqw.orderByAsc(SysDepart::getDepartOrder);
        //update-end---author:wangshuai ---date:20220527  for：[VUEN-1143]排序不对，vue3和2应该都有问题，应该按照升序排--------------
        List<SysDepart> list = list(lqw);
        //update-begin---author:wangshuai ---date:20220316  for：[JTC-119]在部门管理菜单下设置部门负责人 创建用户的时候不需要处理
        //设置用户id,让前台显示
//        this.setUserIdsByDepList(list);
        //update-end---author:wangshuai ---date:20220316  for：[JTC-119]在部门管理菜单下设置部门负责人 创建用户的时候不需要处理
        List<SysDepartTreeModel> records = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            SysDepart depart = list.get(i);
            SysDepartTreeModel treeModel = new SysDepartTreeModel(depart);
            LambdaQueryWrapper<SysDepart> departQuery = new LambdaQueryWrapper<SysDepart>();
            departQuery.eq(SysDepart::getParentId, depart.getId());
            long count = this.count(departQuery);
            if (count >= 1) {
                treeModel.setIsLeaf(false);
            } else {
                treeModel.setIsLeaf(true);
            }
            //TODO 异步树加载key拼接__+时间戳,以便于每次展开节点会刷新数据
            //treeModel.setKey(treeModel.getKey()+"__"+System.currentTimeMillis());
            records.add(treeModel);
        }
        return records;
    }

    private JSONObject queryAllParentIdByDepartId(String departId) {
        JSONObject result = new JSONObject();
        for (String id : departId.split(SymbolConstant.COMMA)) {
            JSONObject all = this.queryAllParentId("id", id);
            result.put(id, all);
        }
        return result;
    }

    private JSONObject queryAllParentIdByOrgCode(String orgCode) {
        JSONObject result = new JSONObject();
        for (String code : orgCode.split(SymbolConstant.COMMA)) {
            JSONObject all = this.queryAllParentId("org_code", code);
            result.put(code, all);
        }
        return result;
    }

    /**
     * 查询某个部门的所有父ID信息
     *
     * @param fieldName 字段名
     * @param value     值
     */
    private JSONObject queryAllParentId(String fieldName, String value) {
        JSONObject data = new JSONObject();
        // 父ID集合，有序
        data.put("parentIds", new JSONArray());
        // 父ID的部门数据，key是id，value是数据
        data.put("parentMap", new JSONObject());
        this.queryAllParentIdRecursion(fieldName, value, data);
        return data;
    }

    /**
     * 递归调用查询父部门接口
     */
    private void queryAllParentIdRecursion(String fieldName, String value, JSONObject data) {
        QueryWrapper<SysDepart> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(fieldName, value);
        SysDepart depart = super.getOne(queryWrapper);
        if (depart != null) {
            data.getJSONArray("parentIds").add(0, depart.getId());
            data.getJSONObject("parentMap").put(depart.getId(), depart);
            if (oConvertUtils.isNotEmpty(depart.getParentId())) {
                this.queryAllParentIdRecursion("id", depart.getParentId(), data);
            }
        }
    }

    /**
     * saveDepartData 对应 add 保存用户在页面添加的新的部门对象数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveDepartData(SysDepart sysDepart, String username) {
        if (sysDepart != null && username != null) {
            //update-begin---author:wangshuai ---date:20230216  for：[QQYUN-4163]给部门表加个是否有子节点------------
            if (oConvertUtils.isEmpty(sysDepart.getParentId())) {
                sysDepart.setParentId("");
            } else {
                //将父部门的设成不是叶子结点
                SysDepart parent = this.getDepartById(sysDepart.getParentId());
                if(parent != null){
                    parent.setIzLeaf(false);
                    this.updateById(parent);
                }
            }
            sysDepart.setId(IdWorker.getIdStr(sysDepart));
            // 先判断该对象有无父级ID,有则意味着不是最高级,否则意味着是最高级
            // 获取父级ID
            String parentId = sysDepart.getParentId();
            //update-begin--Author:baihailong  Date:20191209 for：部门编码规则生成器做成公用配置
            JSONObject formData = new JSONObject();
            formData.put("parentId", parentId);
            String[] codeArray = (String[]) FillRuleUtil.executeRule(FillRuleConstant.DEPART, formData);
            //update-end--Author:baihailong  Date:20191209 for：部门编码规则生成器做成公用配置
            sysDepart.setOrgCode(codeArray[0]);
            String orgType = codeArray[1];
            sysDepart.setOrgType(String.valueOf(orgType));
            sysDepart.setCreateTime(new Date());
            sysDepart.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
            //新添加的部门是叶子节点
//            sysDepart.setIzLeaf(true);
            this.save(sysDepart);
        }

    }
}
